package com.ls.cameraxtest;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;

public class Camera1Fragment extends Fragment implements Camera.PreviewCallback {
    private SurfaceView mSurfaceView;
    private SurfaceHolder mSurfaceHolder;

    //    private int mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
    private int mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
    private Camera mCamera;
    private Camera.Parameters mParameters;


    private int mWidth;
    private int mHeight;

    private File mPicturesPath = null;
    private int mOrientation;

    @Override
    public View onCreateView(
            LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState
    ) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_camera1, container, false);
    }

    @Override
    public void onViewCreated(@NonNull final View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        ((MainActivity)getActivity()).setTitle("我们来用旧版拍照");
        view.findViewById(R.id.button_second).setOnClickListener(view1 -> NavHostFragment.findNavController(Camera1Fragment.this)
                .navigate(R.id.action_Camera1Fragment_to_FirstFragment));
        mPicturesPath = getActivity().getExternalCacheDir();
        mSurfaceView = view.findViewById(R.id.surface_view);
        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {

            @Override
            public void surfaceCreated(@NonNull SurfaceHolder holder) {
                if (null == mCamera) {
                    openCamera(mCameraId);
                }
                startPreview();
            }

            @Override
            public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {

            }

            @Override
            public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
                releaseCamera();
            }
        });

        view.findViewById(R.id.button_take).setOnClickListener(v -> takePicture());
        DisplayMetrics dm = new DisplayMetrics();
        getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
        mWidth = dm.widthPixels;
        mHeight = dm.heightPixels;
    }

    /**
     * 进行拍照
     */
    private void takePicture() {
        if (null != mCamera) {
            mCamera.takePicture(() -> {
            }, (data, camera) -> {
                //base data
            }, (data, camera) -> {
                mCamera.startPreview();
                new Thread(
                        () -> savePhoto(data)
                ).start();
            });
        }
    }

    /**
     * 保存拍摄图片
     */
    private void savePhoto(final byte[] data) {
        if (!mPicturesPath.exists()) {
            mPicturesPath.mkdirs();
        }

        File file = new File(mPicturesPath, System.currentTimeMillis() + ".jpg");
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            fos.write(data);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        rotateImageView(mCameraId, mOrientation, file.getPath());
    }

    private void rotateImageView(int cameraId, int orientation, String path) {
        Log.d("DEBUG", "##### save path: " + path);
        Bitmap bitmap = BitmapFactory.decodeFile(path);


        Bitmap resizeBitmap = null;
        switch (cameraId) {
            case Camera.CameraInfo.CAMERA_FACING_BACK:
                Matrix matrix = new Matrix();
                if (mOrientation == 90) {
                    matrix.postRotate(90);
                }
                resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
                        matrix, true);
                break;
            case Camera.CameraInfo.CAMERA_FACING_FRONT:
                Matrix m = new Matrix();
                m.postScale(-1f, 1f);
                resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
                        m, true);
                break;
            default:
        }

        File file = new File(path);
        try {
            FileOutputStream fos = new FileOutputStream(file);
            resizeBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
            fos.close();
            resizeBitmap.recycle();
        } catch (Exception e) {
            e.printStackTrace();
        }
        ((MainActivity)getActivity()).saveImgToPics(getActivity(),path);
        Looper.prepare();
        Toast.makeText(getActivity(), "save file path: " + path, Toast.LENGTH_LONG).show();
        Looper.loop();
    }


    /**
     * 开启相机
     */
    private void openCamera(final int cameraId) {
        if (isSupport(cameraId)) {
            try {
                //通过相机id获取对应摄像头实例
                mCamera = Camera.open(cameraId);
                //初始化相机参数
                initParameters(mCamera);
                //preview
                if (null != mCamera) {
                    //设置预览数据回调
                    mCamera.setPreviewCallback(this);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 初始化相机参数
     */
    private void initParameters(final Camera camera) {
        //获取相机配置
        mParameters = camera.getParameters();
        //配置图片格式化类型
        mParameters.setPreviewFormat(ImageFormat.NV21);
        //获取支持的预览格式化类型
        mParameters.getSupportedPreviewFormats();
        //获取支持的图片格式化类型
        mParameters.getSupportedPictureFormats();


        if (isSupportFocus(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
            //判断是否支持连续对焦-拍照完成之后继续对焦
            mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
        } else if (isSupportFocus(Camera.Parameters.FOCUS_MODE_AUTO)) {
            //判断是否支持自动对焦
            mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        }

        //配置预览分辨率
        setPreviewSize();
        //配置输出图片的分辨率
        setPictureSize();

        camera.setParameters(mParameters);
    }

    /**
     * 拍照界面预览
     */
    private void startPreview() {
        try {
            mCamera.setPreviewDisplay(mSurfaceHolder);
            setCameraDisplayOrientation();
            mCamera.startPreview();

            startFaceDetect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 人脸识别
     */
    private void startFaceDetect() {
        mCamera.startFaceDetection();
        mCamera.setFaceDetectionListener(new Camera.FaceDetectionListener() {
            @Override
            public void onFaceDetection(Camera.Face[] faces, Camera camera) {
                Log.d("DEBUG", "##### face length: " + faces.length);
            }
        });
    }

    /**
     * 设置预览界面大小
     */
    private void setPreviewSize() {
        //获取支持的预览分辨率
        List<Camera.Size> supportSizes = mParameters.getSupportedPreviewSizes();
        //最大分辨率
        Camera.Size biggestSize = null;
        //刚刚好的分辨率
        Camera.Size fitSize = null;
        //宽高有一个一样的分辨率
        Camera.Size targetSize = null;
        //宽高都小于屏幕的分辨率
        Camera.Size targetSiz2 = null;
        if (null != supportSizes) {
            for (int i = 0; i < supportSizes.size(); i++) {
                Camera.Size size = supportSizes.get(i);
                Log.d("DEBUG", "###### SupportedPreviewSizes: width=" + size.width + ", height=" + size.height);
                if (biggestSize == null || (size.width >= biggestSize.width && size.height >= biggestSize.height)) {
                    biggestSize = size;
                }

                if (size.width == mWidth  && size.height == mHeight) {
                    //支持的分辨率跟屏幕一样
                    fitSize = size;
                } else if (size.width == mWidth|| size.height == mHeight) {
                    //如果任一宽或者高等于所支持的尺寸
                    if (targetSize == null) {
                        targetSize = size;
                    } else if (size.width < mWidth|| size.height < mHeight) {
                        //如果上面条件都不成立 如果任一宽高小于所支持的尺寸
                        targetSiz2 = size;
                    }
                }
            }

            if (fitSize == null) {
                fitSize = targetSize;
            }
            if (fitSize == null) {
                fitSize = targetSiz2;
            }
            if (fitSize == null) {
                fitSize = biggestSize;
            }

            Log.d("DEBUG", "##### fitSize width: " + fitSize.width + ", height: " + fitSize.height);
            mParameters.setPreviewSize(fitSize.width, fitSize.height);
        }
    }

    /**
     * save picture size
     */
    private void setPictureSize() {
        //获取相机支持的输出图片的分辨率
        List<Camera.Size> mPictureSizes = mParameters.getSupportedPictureSizes();
        //预览分辨率尺寸
        Camera.Size previewSize = mParameters.getPreviewSize();
        //最大尺寸
        Camera.Size biggestSize = null;
        // 优先选预览界面的尺寸
        Camera.Size fitSize = null;
        Log.d("DEBUG", "##### preview size: " + previewSize.width + ", height:" + previewSize.height);
        //放大尺寸
        float scaleSize = 0;
        if (null != previewSize) {
            scaleSize = previewSize.width / (float) previewSize.height;
        }

        for (int i = 0; i < mPictureSizes.size(); i++) {
            Camera.Size picture = mPictureSizes.get(i);
            Log.d("DEBUG", "###### SupportedPictureSizes: width=" + picture.width + ", height="
                    + picture.height);
            if (null == biggestSize) {
                biggestSize = picture;
            } else if (picture.width > biggestSize.width && picture.height > biggestSize.height) {
                biggestSize = picture;
            }

            if (scaleSize > 0 && picture.width > previewSize.width && picture.height > previewSize.height) {
                float currentScale = picture.width / (float) picture.height;
                if (scaleSize == currentScale) {
                    if (null == fitSize) {
                        fitSize = picture;
                    } else if (picture.width > fitSize.width && picture.height > fitSize.height) {
                        fitSize = picture;
                    }
                }
            }
        }

        if (null == fitSize) {
            fitSize = biggestSize;
        }

        Log.d("DEBUG", "##### fit size: " + fitSize.width + ", height:" + fitSize.height);
        mParameters.setPictureSize(fitSize.width, fitSize.height);
    }

    /**
     * 释放资源
     */
    private void releaseCamera() {
        if (null != mCamera) {
            mCamera.stopPreview();
            mCamera.stopFaceDetection();
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
        }
    }

    /**
     * 设置横竖向转换
     */
    private void setCameraDisplayOrientation() {
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        Camera.getCameraInfo(mCameraId, cameraInfo);
        int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();  //自然方向
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
            default:
        }

        int result;
        //cameraInfo.orientation 图像传感方向
        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (cameraInfo.orientation + degrees) % 360;
            result = (360 - result) % 360;
        } else {
            result = (cameraInfo.orientation - degrees + 360) % 360;
        }
        Log.d("DEBUG", "##### setCameraDisplayOrientation rotation: " + rotation
                + ", cameraInfo.orientation: " + cameraInfo.orientation + ", result: " + result);

        mOrientation = result;
        //相机预览方向
        mCamera.setDisplayOrientation(result);
    }

    /**
     * 判断是否支持前后摄像头
     */
    private boolean isSupport(int backOrFront) {
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
            Camera.getCameraInfo(i, cameraInfo);
            if (cameraInfo.facing == backOrFront) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否支持对焦
     */
    private boolean isSupportFocus(String focusMode) {
        for (String mode : mParameters.getSupportedFocusModes()) {
            if (focusMode.equals(mode)) {
                return true;
            }
        }

        return false;
    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {

    }
}